home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / PowerPlant / LConsoleAttachment / LConsoleAttachment.cp next >
Encoding:
Text File  |  1995-03-12  |  9.5 KB  |  315 lines  |  [TEXT/CWIE]

  1. // LConsoleAttachment.h - Attachment which pumps events through SIOUX.
  2. /******************************************************************************\
  3. Copyright (c) 1995 by Ken Badertscher (KenBad@aol.com).  All Rights Reserved.
  4.  
  5. Permission to use, copy, modify, distribute and sell this software and its
  6. documentation for any purpose is hereby granted without fee, provided that
  7. the above copyright notice appear in all copies and that both that copyright
  8. notice and this permission notice appear in supporting documentation.
  9. Ken Badertscher makes no representations about the suitability of this software
  10. for any purpose.  It is provided "as is" without express or implied warranty.
  11.  
  12.     Mail kudos & brickbats to KenBad@aol.com.
  13.  
  14. History:
  15.     95-10-30 kbad    Added command mapping to let SIOUX use app menus.
  16.     95-10-15 kbad    Added auto-close flag
  17.     95-03-12 kbad    Created
  18.  
  19. TODO:
  20. \******************************************************************************/
  21.  
  22. #ifndef LCONSOLEATTACHMENT_H
  23. #include "LConsoleAttachment.h"
  24. #endif
  25.  
  26. #include <SIOUX.h>
  27. #include <LMenuBar.h>
  28. #include <Processes.h>
  29. #include <Windows.h>
  30.  
  31. // Danger, Will Robinson... these functions are not explicitly exported
  32. // by SIOUX (though they should be!).  Alternatives involve gross hackery.
  33. //
  34. extern "C" {
  35.  
  36. // SIOUXIsAppWindow could be circumvented if it was assumed that all other
  37. // app windows are PowerPlant windows.  Then LConsoleAttachment::SIOUXIsFront
  38. // could look up the refCon in the window list.
  39. //
  40. Boolean SIOUXIsAppWindow(const WindowRef);
  41.  
  42. // Note that even without the following, the command-key event hackery in
  43. // LConsoleAttachment::CommandKeyEvent should force SIOUX to do the right thing,
  44. // albeit much less cleanly.
  45. //
  46. void SIOUXDoEditCut();
  47. void SIOUXDoEditCopy();
  48. void SIOUXDoEditPaste();
  49. void SIOUXDoEditClear();
  50. void SIOUXDoEditSelectAll();
  51. void SIOUXDoSaveText();
  52. void SIOUXDoPrintText();
  53. void SIOUXUpdateScrollbar();
  54.  
  55. } // extern "C"
  56.  
  57.  
  58. // Global decls
  59. //==============================================================================
  60.  
  61. // Default console attachment, useful if no customization is needed.
  62. //
  63. LConsoleAttachment gConsoleAttachment;
  64.  
  65. // Local decls
  66. //==============================================================================
  67.  
  68. // StFlushSIOUX
  69. //==============================================================================
  70.  
  71. StFlushSIOUX::~StFlushSIOUX()
  72. {
  73. /*----------------------------------------------------------------------------*\
  74.     work around flush manipulator not updating scrollbar
  75. \*----------------------------------------------------------------------------*/
  76.     ::SIOUXUpdateScrollbar();
  77. }
  78.  
  79.  
  80. // LConsoleAttachment
  81. //==============================================================================
  82.  
  83.  
  84. LConsoleAttachment::LConsoleAttachment(StringPtr title,
  85.                                        EAutoClose close, EAskSave askSave)
  86. : LAttachment(msg_AnyMessage), mTitleSet(false), mCommandsCached(false)
  87. {
  88. /*----------------------------------------------------------------------------*\
  89.     default c'tor
  90. \*----------------------------------------------------------------------------*/
  91.     // set up SIOUX behavior
  92.     //
  93.     SIOUXSettings.initializeTB = SIOUXSettings.setupmenus = false;
  94.     SIOUXSettings.autocloseonquit = (close==kAutoClose);
  95.     SIOUXSettings.asktosaveonclose = (askSave==kAskSave);
  96.  
  97.     // set console window title
  98.     // If this isn't set here, a default title is set when the window
  99.     // is first shown.
  100.     if (title)
  101.         mTitle = title;
  102. }
  103.  
  104.  
  105. LConsoleAttachment::~LConsoleAttachment()
  106. {
  107. /*----------------------------------------------------------------------------*\
  108.     d'tor
  109. \*----------------------------------------------------------------------------*/
  110. }
  111.  
  112.  
  113. LConsoleAttachment::LConsoleAttachment(const LConsoleAttachment&)
  114. { // private, unimplemented
  115. /*----------------------------------------------------------------------------*\
  116.     copy c'tor
  117. \*----------------------------------------------------------------------------*/
  118. }
  119.  
  120.  
  121. LConsoleAttachment& LConsoleAttachment::operator=(const LConsoleAttachment&)
  122. { // private, unimplemented
  123. /*----------------------------------------------------------------------------*\
  124.     assignment
  125. \*----------------------------------------------------------------------------*/
  126.     return *this;
  127. }
  128.  
  129.  
  130. void LConsoleAttachment::ExecuteSelf(MessageT inMessage, void *ioParam)
  131. {
  132. /*----------------------------------------------------------------------------*\
  133.     Dispatch the message.
  134.     If it's an event message, always pass it to SIOUX.
  135.     Only pass commands & cursor adjustments when SIOUX window is frontmost.
  136. \*----------------------------------------------------------------------------*/
  137.     mExecuteHost = true;
  138.     if (inMessage == msg_Event)
  139.     {
  140.         DispatchEvent(*(EventRecord *)ioParam);
  141.     }
  142.     else if (SIOUXIsFront())
  143.     {
  144.         switch (inMessage)
  145.         {
  146.         case msg_CommandStatus:
  147.             FindCommandStatus(*(SCommandStatus *)ioParam);
  148.         break;
  149.  
  150.         case msg_AdjustCursor:
  151.             AdjustCursor(*(EventRecord *)ioParam);
  152.         break;
  153.  
  154.         //case cmd_Close:
  155.         case cmd_Save:        ::SIOUXDoSaveText();        break;
  156.         case cmd_Print:        ::SIOUXDoPrintText();        break;
  157.         //case cmd_Undo:
  158.         case cmd_Cut:        ::SIOUXDoEditCut();            break;
  159.         case cmd_Copy:        ::SIOUXDoEditCopy();        break;
  160.         case cmd_Paste:        ::SIOUXDoEditPaste();        break;
  161.         case cmd_Clear:        ::SIOUXDoEditClear();        break;
  162.         case cmd_SelectAll:    ::SIOUXDoEditSelectAll();    break;
  163.  
  164.         // Pass other potential menu commands through as key commands
  165.         default:            ObeyCommand(inMessage, ioParam);
  166.         }
  167.     }
  168. }
  169.  
  170. void LConsoleAttachment::FindCommandStatus(const SCommandStatus &status)
  171. {
  172. /*----------------------------------------------------------------------------*\
  173.     Enable SIOUX-related menu commands when console window is frontmost.
  174. \*----------------------------------------------------------------------------*/
  175.     EventRecord e;
  176.     switch (status.command)
  177.     {
  178.  
  179.     // Commands handled directly by SIOUX:
  180.     //
  181.     //case cmd_Close:
  182.     case cmd_Save:
  183.     case cmd_Print:
  184.     //case cmd_Undo:
  185.     case cmd_Cut:
  186.     case cmd_Copy:
  187.     case cmd_Paste:
  188.     case cmd_Clear:
  189.     case cmd_SelectAll:
  190.         *status.enabled = true;
  191.         *status.usesMark = false;
  192.         mExecuteHost = false;
  193.     break;
  194.  
  195.     // Other commands with key equivalents:
  196.     //
  197.     default:
  198.         if (CommandKeyEvent(status.command, e))
  199.         {
  200.             *status.enabled = true;
  201.             *status.usesMark = false;
  202.             mExecuteHost = false;
  203.         }
  204.     }
  205. }
  206.  
  207.  
  208. Boolean LConsoleAttachment::CommandKeyEvent(CommandT inCommand, EventRecord& e)
  209. {
  210. /*----------------------------------------------------------------------------*\
  211.     Create a command key event for a menu command.
  212.     This will be invoked only if the console window is frontmost,
  213.     meaning that menus are up.
  214. \*----------------------------------------------------------------------------*/
  215.     if (inCommand > kNumCommands) e.message = 0;
  216.     else
  217.     {
  218.         if (!mCommandsCached)
  219.         {
  220.             // Set up command key message cache.
  221.             // Not done in constructor, because menus might not be up yet.
  222.             //
  223.             for (int i = 0; i < kNumCommands; i++)
  224.             {
  225.                 mCommandKeyEvent[i] = 0;
  226.                 ResIDT menuID;
  227.                 MenuHandle menuH;
  228.                 Int16 menuItem;
  229.                 LMenuBar::GetCurrentMenuBar()->
  230.                     FindMenuItem(i, menuID, menuH, menuItem);
  231.                 if (menuH)
  232.                 {
  233.                     // Look up key equivalent in menu.
  234.                     // If it's not a special char (submenu, script code,
  235.                     // ICON, SICN), set the event message for that command.
  236.                     //
  237.                     short cmdChar;
  238.                     ::GetItemCmd(menuH, menuItem, &cmdChar);
  239.                     if (!cmdChar && i == cmd_Clear)
  240.                         mCommandKeyEvent[i] = 0x3308; // vkey | char_Backspace;
  241.                     else if (cmdChar < 0x1b || 0x1e < cmdChar)
  242.                         mCommandKeyEvent[i] = cmdChar;
  243.                 }
  244.             }
  245.             mCommandsCached = true;
  246.         }
  247.  
  248.         // Fill in the event record for this command.
  249.         //
  250.         e.what = keyDown;
  251.         e.modifiers = (inCommand == cmd_Clear) ? 0 : cmdKey;
  252.         e.message = mCommandKeyEvent[inCommand];
  253.     }
  254.  
  255.     return (e.message != 0);
  256. }
  257.  
  258. void LConsoleAttachment::AdjustCursor(const EventRecord &inMacEvent)
  259. {
  260. /*----------------------------------------------------------------------------*\
  261.     Let SIOUX adjust the cursor when the console is frontmost
  262. \*----------------------------------------------------------------------------*/
  263.     EventRecord e = inMacEvent;
  264.     e.what = nullEvent;
  265.     ::SIOUXHandleOneEvent(&e);
  266.     mExecuteHost = false; // never execute in host--it will always set an arrow
  267. }
  268.  
  269. void LConsoleAttachment::DispatchEvent(const EventRecord& inMacEvent)
  270. {
  271. /*----------------------------------------------------------------------------*\
  272.     SIOUX event pump
  273. \*----------------------------------------------------------------------------*/
  274. #ifndef OM_NoExplicitTemplates
  275.     EventRecord *evptr = const_cast<EventRecord *>(&inMacEvent);
  276. #endif
  277.     mExecuteHost = !::SIOUXHandleOneEvent(evptr);
  278. }
  279.  
  280. void LConsoleAttachment::ObeyCommand(CommandT inCommand, void *ioParam)
  281. {
  282. /*----------------------------------------------------------------------------*\
  283.     Translate menu commands to key commands for SIOUX.
  284. \*----------------------------------------------------------------------------*/
  285. #pragma unused (ioParam)
  286.     EventRecord e;
  287.     if (CommandKeyEvent(inCommand, e))
  288.         mExecuteHost = !::SIOUXHandleOneEvent(&e);
  289. }
  290.  
  291. Boolean LConsoleAttachment::SIOUXIsFront()
  292. {
  293. /*----------------------------------------------------------------------------*\
  294.     Return true if SIOUX window is frontmost.
  295.     The first time it is frontmost, set its title.
  296. \*----------------------------------------------------------------------------*/
  297.     WindowRef frontWind = ::FrontWindow();
  298.     Boolean result = (frontWind && ::SIOUXIsAppWindow(frontWind));
  299.     if (result && !mTitleSet)
  300.     {
  301.         if (mTitle.Length() == 0)
  302.         {
  303.             ProcessSerialNumber psn;
  304.             ::GetCurrentProcess(&psn);
  305.             ProcessInfoRec pinfo;
  306.             ::GetProcessInformation(&psn, &pinfo);
  307.             mTitle = pinfo.processName;
  308.             mTitle += "\p Console";
  309.         }
  310.  
  311.         ::SIOUXSetTitle(mTitle);
  312.         mTitleSet = true;
  313.     }
  314.     return result;
  315. }